package top.gytf.unifiedcall.jsr269;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import javax.annotation.processing.Messager;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

import static java.lang.String.format;

/**
 * 相关工具
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Utils {
    private static final String STATUS_CODE_CLASSNAME = "top.gytf.unifiedcall.model.code.StatusCode";

    /**
     * 获取编码枚举值的定位描述
     */
    public static String getCodeLocation(VariableElement codeConstantElement, Messager messager) {
        if (!ElementKind.ENUM_CONSTANT.equals(codeConstantElement.getKind())) {
            messager.printMessage(Diagnostic.Kind.WARNING, format("忽略[%s]：非EnumConstant类型", codeConstantElement));
            return null;
        }
        TypeElement enumElement = (TypeElement) codeConstantElement.getEnclosingElement();
        return format("%s#%s", enumElement.getQualifiedName(), codeConstantElement.getSimpleName());
    }

    /**
     * 扫描编码的枚举实现类，获取其所有符合条件的枚举值
     */
    public static List<VariableElement> scanCodes(Element enumElement, Messager messager, Predicate<VariableElement> filter) {
        return scanCodes(enumElement, messager, null, filter);
    }

    /**
     * 扫描指定编码的枚举实现类，获取其所有符合条件的枚举值
     */
    public static List<VariableElement> scanCodes(Element enumElement, Messager messager, String codeClassName, Predicate<VariableElement> filter) {
        if (!ElementKind.ENUM.equals(enumElement.getKind())) {
            messager.printMessage(Diagnostic.Kind.WARNING, format("忽略[%s]：非Enum类型", enumElement));
            return Collections.emptyList();
        }
        if (codeClassName != null) {
            TypeElement typeElement = (TypeElement) enumElement;
            boolean isCodeImpl = typeElement.getInterfaces().stream()
                    .map(TypeMirror::toString)
                    .anyMatch(codeClassName::equals);
            if (!isCodeImpl) {
                messager.printMessage(Diagnostic.Kind.WARNING, format("忽略[%s]：非%s实现", enumElement, codeClassName));
                return Collections.emptyList();
            }
        }

        return enumElement.getEnclosedElements().stream()
                // 只处理未被GenException.Ignore标注的枚举值
                .filter(e -> ElementKind.ENUM_CONSTANT.equals(e.getKind()))
                .map(VariableElement.class::cast)
                .filter(filter)
                .toList();
    }

    /**
     * 扫描状态码的枚举实现类，获取其所有符合条件的枚举值
     */
    public static List<VariableElement> scanStatusCodes(Element enumElement, Messager messager, Predicate<VariableElement> filter) {
        return scanCodes(enumElement, messager, STATUS_CODE_CLASSNAME, filter);
    }
}
